package com.elvish.oda.common.utils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.shiro.SecurityUtils;
import org.nutz.dao.Cnd;
import org.nutz.dao.entity.annotation.Column;
import org.nutz.dao.sql.Criteria;
import org.nutz.dao.util.cri.SqlExpressionGroup;
import org.nutz.lang.Lang;

import com.elvish.oda.busin.anno.Operator;
import com.elvish.oda.busin.pojo.User;
import com.elvish.oda.common.pojo.Page;

public class CommonUtil {

	/**
	 * 获取当前登录用户
	 * 
	 * @return 当前用户对象
	 */
	public static User getCurrentUser() {
		return (User) SecurityUtils.getSubject().getPrincipal();
	}

	/**
	 * 构建树形结构
	 * 
	 * @param list
	 *            数据集合
	 * @param pidName
	 *            父类标识字段
	 * @return 树形结构集合
	 */
	public static <T> List<T> buildTree(List<T> list, String pidName) {

		Map<Integer, T> temp = new HashMap<Integer, T>();
		for (T obj : list) {
			temp.put(Integer.parseInt(getObjFieldValue(obj, "id").toString()), obj);
		}

		return buildTree(temp, list, pidName);
	}

	private static <T> List<T> buildTree(Map<Integer, T> temp, List<T> list, String pidName) {
		List<T> rootMenus = new ArrayList<T>();
		for (T obj : list) {
			// 获取一级节点数据
			T parent = temp.get(getObjFieldValue(obj, pidName));
			if (parent == null) {
				// 添加一级节点数据
				rootMenus.add(obj);
			} else {
				buildChildren(parent, obj);
			}

		}
		return rootMenus;
	}

	private static <T> void buildChildren(T parent, T obj) {
		// 二级及二级以下节点
		// parent为二级
		List<T> children = (List<T>) getObjFieldValue(parent, "children");
		if (children == null) {
			children = new ArrayList<T>();
			setObjFieldValue(parent, "setChildren", children);
		}
		children.add(obj);
	}

	/**
	 * 调用模型方法
	 * 
	 * @param obj
	 *            模型
	 * @param methodName
	 *            方法
	 * @param list
	 *            数据集合
	 */
	private static <T> void setObjFieldValue(T obj, String methodName, List<T> list) {
		Class<?> clz = obj.getClass();
		Method method;
		try {
			method = clz.getDeclaredMethod(methodName, List.class);
			if (method.isAccessible()) {
				method.setAccessible(true);
			}
			method.invoke(obj, list);
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 获取模型属性值
	 * 
	 * @param obj
	 *            模型
	 * @param fieldName
	 *            属性名称
	 * @return 模型属性值
	 */
	private static <T> T getObjFieldValue(Object obj, String fieldName) {
		Class<?> clz = obj.getClass();
		Field field;
		try {
			field = clz.getDeclaredField(fieldName);
			if (!field.isAccessible()) {
				field.setAccessible(true);
			}
			return (T) field.get(obj);
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NumberFormatException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		return null;
	}

	public static String limit(String sql, Page page) {
		StringBuilder sb = new StringBuilder();
		sb.append(sql);
		sb.append(" limit ");
		sb.append(page.getStart());
		sb.append(",");
		sb.append(page.getRows());
		return sb.toString();
	}

	public static Criteria getCriteria(Object obj) {
		Criteria cri = Cnd.cri();
		Class<?> clz = obj.getClass();
		Field[] fields = clz.getDeclaredFields();
		for (Field field : fields) {
			if (!field.isAccessible()) {
				field.setAccessible(true);
			}
			// 判断值为不为空
			try {
				if (!Lang.isEmpty(field.get(obj))) {
					if (field.get(obj).toString().length() == 0) {
						continue;
					}
					// 获取nutz字段注解
					Column column = field.getAnnotation(Column.class);
					if (column == null) {
						continue;
					}
					// 获取数据库字段名称
					String columnName = (column.value() == "" || column.value().length() == 0) ? field.getName()
							: column.value();
					// 获取操作符
					Operator oper = field.getAnnotation(Operator.class);
					if (oper == null) {
						continue;
					}
					// 封装条件并塞入条件集合
					SqlExpressionGroup expression = Cnd.exps(columnName, oper.value(), field.get(obj));
					if ("like".equals(oper.value())) {
						expression = Cnd.exps(columnName, oper.value(), "%" + field.get(obj) + "%");
					}

					cri.where().and(expression);
				}
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
		return cri;
	}

}
